package models

import (
	"api/app/auth/auto/v1/mc"
	"api/libs/orm"
	"gitee.com/dreamwood/ez"

	"api/libs/errs"
	"context"
	"errors"
	"fmt"
)

func (this Page) TableName() string {
	return "auth_page"
}

func (this Page) MakeChoice() ez.M {
	return ez.M{"value": this.Id, "label": this.Name, "level": this.Level}
}

func init() {
	conf := mc.GetPageEzConfig()
	conf.Crud["default"] = orm.EzModelFieldLimitation{
		Select:    []string{},        //snake写法，多对一应该写xxx_id,关联关系不应该写在这里，使用Relations配置项
		Omit:      []string{},        //select优先级高于Omit,如果select和omit同时设置了，omit不生效
		Relations: []string{"Roles"}, //大驼峰写法
	}
	conf.Crud["lr"] = orm.EzModelFieldLimitation{
		Select:    []string{"l", "r", "link", "level"}, //snake写法，多对一应该写xxx_id,关联关系不应该写在这里，使用Relations配置项
		Omit:      []string{},                          //select优先级高于Omit,如果select和omit同时设置了，omit不生效
		Relations: []string{},
	}
}

type PageTreeModel struct{}

func (this PageTreeModel) UpdateLeftAndRight(rootId int, count int, level int) int {
	crud := NewPageCrud()
	sons, e := crud.FindBy(ez.M{"parentId": rootId}, []string{"sort"}, 0, 0)
	count++
	if e != nil {
		return count
	}
	if len(sons) == 0 {
		return count
	}
	for _, son := range sons {
		son.Level = level
		link, isCircle := this.GetParents(son.Id)
		if isCircle {
			ez.PrintError(errors.New("闭环循环"))
		}
		son.Link = link
		son.L = count
		son.Save("lr")
		//进入子分类继续
		son.R = this.UpdateLeftAndRight(son.Id, count, level+1)
		count = son.R
		son.Save("lr")
		count++
	}
	return count
}
func (this PageTreeModel) ClearDirtyParent() {
	crud := NewPageCrud()
	all, e := crud.FindBy(ez.M{}, nil, 0, 0)
	if errs.Try(e) {
		return
	}
	ids := make([]int, 0)
	for _, row := range all {
		ids = append(ids, row.Id)
	}
	missed, e := crud.FindBy(ez.M{"parentId__nin": ids}, nil, 0, 0)
	for _, item := range missed {
		item.ParentId = 0
		item.Save()
	}
}

// 获取父级元素，检测闭环
func (this PageTreeModel) GetParents(curId int) (link string, isCircled bool) {
	crud := NewPageCrud()
	cur, e := crud.Find(curId)
	if e != nil {
		errs.Get(e)
		return
	}
	//闭环检测
	log := make(map[int]bool)
	for {
		if cur.ParentId == 0 {
			return link, isCircled //没有闭环
		}
		parent, e := crud.Find(cur.ParentId)
		if e != nil {
			errs.Get(e)
			return
		}
		if parent == nil {
			return link, isCircled //没有闭环
		}
		//检测到闭环 就直接退出
		logFind, ok := log[parent.Id]
		if ok && logFind {
			isCircled = true
			return link, isCircled
		}
		link = fmt.Sprintf("%d_%s", parent.L, link)
		log[parent.Id] = true
		cur = parent
	}
}

// 绑定一个事件监听
func init() {
	ez.ListenJoin(mc.PageEventAfterSave, func(v interface{}, ctx context.Context) {
		_, ok := v.(*Page)
		if ok {
			PageTreeModel{}.UpdateLeftAndRight(0, 0, 0)
		}
	})
}
